#include "thttpd.h"
#include <sys/types.h>
#include <sys/wait.h>
#include "custom_handle.h"
#include <unistd.h>

// 处理控制命令的线程
void *ctrl_worker(void *arg)
{
	int msgid = msgget(MSG_KEY, IPC_CREAT | 0666);
	ctrl_msg_t msg;
	modbus_t *ms = modbus_new_tcp("192.168.51.9", 502);
	modbus_set_slave(ms, 1);
	modbus_connect(ms);
	while (1)
	{
		if (msgrcv(msgid, &msg, sizeof(msg.cmd), 0, 0) > 0)
		{
			if (strcmp(msg.cmd, "led_on") == 0)
			{
				modbus_write_bit(ms, 1, 1); // 1为LED线圈地址
			}
			else if (strcmp(msg.cmd, "led_off") == 0)
			{
				modbus_write_bit(ms, 1, 0);
			}
			else if (strcmp(msg.cmd, "buzzer_on") == 0)
			{
				modbus_write_bit(ms, 0, 1); // 0为蜂鸣器线圈地址
			}
			else if (strcmp(msg.cmd, "buzzer_off") == 0)
			{
				modbus_write_bit(ms, 0, 0);
			}
		}
	}
	modbus_close(ms);
	modbus_free(ms);
	return NULL;
}
// 采集传感器数据放入共享内存中
void *sensor_collector(void *arg)
{
	int shmid = shmget(SHM_KEY, sizeof(sensor_data_t), IPC_CREAT | 0666);
	sensor_data_t *pdata = (sensor_data_t *)shmat(shmid, NULL, 0);
	char buf[48] = {0};
	uint16_t dest[48] = {0};
	while (1)
	{
		modbus_t *ms = modbus_new_tcp("192.168.51.9", 502);
		modbus_set_slave(ms, 1);
		modbus_connect(ms);
		modbus_read_registers(ms, 0, 2, dest);
		modbus_close(ms);
		modbus_free(ms);

		int a = dest[0], b = dest[1];
		pdata->value1 = a;
		pdata->value2 = b;
		sleep(2); // 每2秒采集一次
	}
	shmdt(pdata);
	return NULL;
}

// 处理请求的线程
static void *msg_request(void *arg)
{
	// 这里客户端描述符通过参数传进来了
	int sock = *(int *)arg;

	// 一般情况下，线程终止后，其终止状态一直保留到其它线程调用pthread_join获取它的状态为止。
	// 但是线程也可以被置为detach状态，这样的线程一旦终止就立刻回收它占用的所有资源，而不保留终止状态。
	pthread_detach(pthread_self());

	// handler_msg作为所有的请求处理入口
	return (void *)handler_msg(sock);
}

int main(int argc, char *argv[])
{
	// 如果不传递端口，那么使用默认端口80
	int port = 80;

	if (argc > 1)
	{
		port = atoi(argv[1]);
	}

	// 初始化服务器
	int lis_sock = init_server(port);

	// 创建线程，用于采集传感器数据
	pthread_t tid_collector;
	pthread_create(&tid_collector, NULL, sensor_collector, NULL);
	// 创建线程，用于处理控制命令
	pthread_t tid_ctrl;
	pthread_create(&tid_ctrl, NULL, ctrl_worker, NULL);

	while (1)
	{
		struct sockaddr_in peer;
		socklen_t len = sizeof(peer);

		int sock = accept(lis_sock, (struct sockaddr *)&peer, &len);

		if (sock < 0)
		{
			perror("accept failed");
			continue;
		}

		// 每次接收一个链接后，会自动创建一个线程，这实际上就是线程服务器模型的应用
		pthread_t tid;
		if (pthread_create(&tid, NULL, msg_request, &sock) > 0)
		{
			perror("pthread_create failed");
			close(sock);
		}
	}
	return 0;
}
